#ifndef A8_UUID_HPP
#define A8_UUID_HPP

#include <string>
#include <a8/xvalue.hpp>
#include <a8/sysutils.hpp>

namespace a8
{
	namespace uuid
	{
#if 0
		const unsigned long long TW_EPOCH  = 1288834974657ULL;
#endif
		const unsigned long long EVA_EPOCH = 1419120000000ULL;
		//毫秒级时间41位+机器ID 10位+毫秒内序列12
		class SnowFlake
		{
		public:
			SnowFlake():
				mMachineId(0),
				mSequenceId(0),
				mLastGenerateTick(0)
			{
			}

			unsigned long long Generate()
			{
				unsigned long long value = 0;
				unsigned long long time = getMilliSecond();
				if(time == mLastGenerateTick){//同一微妙内
					mSequenceId++;
					if (mSequenceId >= 0x1000){ //计数已经用完
						while(time <= mLastGenerateTick){
							usleep(1);
							time = getMilliSecond();
						}
						mSequenceId = 0;
					}			
				}else{
					mSequenceId = 0;
				}
				mLastGenerateTick = time;
				assert(time > EVA_EPOCH);
				time = time - EVA_EPOCH;
				
				// 保留后41位时间
				value = time << 22;

				// 中间10位是机器ID
				value |= (mMachineId & 0x3FF) << 12;

				// 最后12位是sequenceID
				value |= mSequenceId & 0xFFF;
				return value;
			}

			void SetMachineId(unsigned int machineid)
			{
				mMachineId = machineid;
			}

		private:
			unsigned short mMachineId; //10 bit
			unsigned short mSequenceId; //12 bit
			unsigned long long mLastGenerateTick;
		};
	}
}

#endif
